

package com.jysz.certificate.service.generator;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import javax.annotation.Resource;

import org.springframework.orm.hibernate3.HibernateOptimisticLockingFailureException;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.stereotype.Service;

import com.jysz.certificate.persistence.dao.SequenceNumberDao;
import com.jysz.certificate.persistence.model.system.SequenceNumber;
import com.jysz.certificate.persistence.model.system.SequenceNumber.SequenceType;
import com.jysz.webcore.ssh.service.EntityService;

/**
 * 对序号进行生成
 * @author <a href="mailto:javaengine@outlook.com">Kaca Rich</a>
 *
 */
@Service
public class SeqGenerator extends EntityService<SequenceNumber, Long, SequenceNumberDao> implements ISeqGenerator {
	
	
	//private static final String MESSAGE_NEED_DELEGATE_OBJECT_STR = "需要的代理对象";
	
	/** 同步锁定使用 * */
	private Lock lock = new ReentrantLock();
	private HibernateTemplate hibernateTemplate;
	
	@Resource
	private SequenceNumberDao sequenceNumberDao;
	
	public SequenceNumberDao getEntityDao() {
		return sequenceNumberDao;
	}
	
	/**
	 * @see com.jysz.certificate.service.generator.ISeqGenerator#generateNextSeqNumber(java.lang.String)
	 */
	public String generateNextSeqNumber(final String clazzName) {
		return generateNextSeqNumber(new DefaultGeneratorDelegate(SequenceType.序号, clazzName));
	}
	
	/**
	 * @see com.jysz.certificate.service.generator.ISeqGenerator#generateNextSeqNumber(java.lang.String, com.wind.steel.model.system.bg.SequenceNumber.SequenceType, java.lang.Object[])
	 */
	public String generateNextSeqNumber(String clazzName, SequenceType type, Object ... otherFormatObjs) {
		return generateNextSeqNumber(new DefaultGeneratorDelegate(type, clazzName));
	}

	/**
	 * @see com.jysz.certificate.service.generator.ISeqGenerator#generateNextSeqNumber(com.jysz.certificate.service.generator.IGeneratorDelegate, java.lang.Object[])
	 */
	public String generateNextSeqNumber(IGeneratorDelegate delegate, Object ... otherFormatObjs) {
		if(delegate == null ){
			return null;
		}
		
		SequenceNumber seq = null;
		try {
			HibernateTemplate ht = getHibernateTemplate();

			seq = delegate.findCurrentSeqNumber(ht);
			if (seq == null) { // 新建序列对象

				try {
					lock.lock();
					seq = delegate.findCurrentSeqNumber(ht);
					if (seq == null) {
						seq = delegate.newSequenceNumber(ht);
						this.save(seq);
					}
				} finally {
					lock.unlock();
				}
			}
			// 判断一下步长，避免出现0的现象
			if (seq.getStepNum() == 0) {
				seq.setStepNum(1);
			}
			
			int nextSeq = seq.getCurrentNum() + seq.getStepNum();

			seq.setCurrentNum(nextSeq);

			this.save(seq);
			this.getEntityDao().getSession().flush();
//			Arrays.asList(otherFormatObjs);
			return seq.getSeqNumFormatted(otherFormatObjs);

		} catch (HibernateOptimisticLockingFailureException e) { // 捕获乐观锁定
			//rereade from database
			if(seq!=null){
				//FIX org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect)
				refresh(seq);
				
			}
			return generateNextSeqNumber(delegate);
		}

	}

	private void refresh(SequenceNumber seq) {
		this.getHibernateTemplate().refresh(seq);
	}

	private HibernateTemplate getHibernateTemplate() {
		if (this.hibernateTemplate == null || this.getEntityDao().getSessionFactory() != this.hibernateTemplate.getSessionFactory()) {
			this.hibernateTemplate = new HibernateTemplate(this.getEntityDao().getSessionFactory());
		}
		return this.hibernateTemplate;
	}

}